package xiaozhi.modules.chat.service.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xiaozhi.common.exception.ErrorCode;
import xiaozhi.common.exception.RenException;
import xiaozhi.modules.agent.entity.AgentEntity;
import xiaozhi.modules.agent.service.AgentService;
import xiaozhi.modules.chat.dto.ChatDTO;
import xiaozhi.modules.chat.dto.MemDTO;
import xiaozhi.modules.chat.entity.ChatHistory;
import xiaozhi.modules.chat.entity.ChatMemory;
import xiaozhi.modules.chat.entity.ChatMessage;
import xiaozhi.modules.chat.service.ChatHistoryService;
import xiaozhi.modules.chat.service.ChatMemoryService;
import xiaozhi.modules.chat.service.ChatMessageService;
import xiaozhi.modules.chat.service.ChatService;
import xiaozhi.modules.device.entity.DeviceEntity;
import xiaozhi.modules.device.service.DeviceService;

import java.util.Date;

/**
 * 类
 *
 * @author wanglunhui
 * @since 2025-04-25 11:24:54
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ChatServiceImpl implements ChatService {

    private final ChatHistoryService chatHistoryService;
    private final ChatMessageService chatMessageService;
    private final ChatMemoryService chatMemoryService;
    private final DeviceService deviceService;
    private final AgentService agentService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String chat(ChatDTO chatDTO) {
        // FieldMetaObjectHandler.insertFill/updateFill
        Date date = new Date();

        String chatHistoryId = chatDTO.getChatHistoryId();
        String macAddress = chatDTO.getMacAddress();
        String faceId = chatDTO.getFaceId();
        String role = chatDTO.getRole();
        String content = chatDTO.getContent();
        Integer promptTokens = chatDTO.getPromptTokens();
        Integer totalTokens = chatDTO.getTotalTokens();
        Integer completionTokens = chatDTO.getCompletionTokens();
        Integer promptMs = chatDTO.getPromptMs();
        Integer totalMs = chatDTO.getTotalMs();
        Integer completionMs = chatDTO.getCompletionMs();
        Integer sequence = chatDTO.getSequence();

        if (StringUtils.isNotBlank(chatHistoryId)) {
            ChatHistory chatHistory = chatHistoryService.selectById(chatHistoryId);
            if (chatHistory == null) {
                chatHistoryId = null;
            } else {
                this.insertChatMessage(chatHistoryId, role, content, promptTokens, totalTokens, completionTokens, promptMs, totalMs, completionMs, sequence, date);

                chatHistory.setMessageCount(chatHistory.getMessageCount() + 1);
                chatHistory.setUpdateDate(date);

                chatHistoryService.updateById(chatHistory);
            }
        }
        if (StringUtils.isBlank(chatHistoryId)) {
            DeviceEntity device = this.getDeviceByMacAddress(macAddress);
            String agentId = device.getAgentId();

            Long userId = device.getUserId();
            String deviceId = device.getId();
            int messageCount = 1; // 一开始就有 1 条

            chatHistoryId = this.insertChatHistory(userId, agentId, deviceId, faceId, messageCount, date);

            this.insertChatMessage(chatHistoryId, role, content, promptTokens, totalTokens, completionTokens, promptMs, totalMs, completionMs, sequence, date);
        }

        return chatHistoryId;
    }

    @Override
    public String SaveMem(MemDTO memDTO) {
        ChatMemory chatMem = new ChatMemory();
        chatMem.setId(memDTO.getId());
        chatMem.setChat_id(memDTO.getChat_id());
        chatMem.setCreate_date(new Date());
        chatMem.setMem_result(memDTO.getMem_result());

        boolean flag = chatMemoryService.insert(chatMem);
        if (flag)
            return SUCCESS_RESULT;
        else
            return FAILED_RESULT;
    }

    // ConfigServiceImpl.getAgentModels()
    public DeviceEntity getDeviceByMacAddress(String macAddress) {
        DeviceEntity device = deviceService.getDeviceByMacAddress(macAddress);
        if (device == null) {
            // 如果设备，去 redis 里看看有没有需要连接的设备
            String cachedCode = deviceService.geCodeByDeviceId(macAddress);
            if (org.apache.commons.lang3.StringUtils.isNotBlank(cachedCode)) {
                throw new RenException(ErrorCode.OTA_DEVICE_NEED_BIND, cachedCode);
            }
            throw new RenException(ErrorCode.OTA_DEVICE_NOT_FOUND, "not found device");
        }

        return device;
    }

    // ConfigServiceImpl.getAgentModels()
    public AgentEntity getAgentByMacAddress(String agentId) {
        AgentEntity agent = agentService.getAgentById(agentId);
        if (agent == null) {
            throw new RenException("智能体未找到");
        }
        return agent;
    }

    public void insertChatMessage(String chatHistoryId, String role, String content, Integer promptTokens, Integer totalTokens, Integer completionTokens, Integer promptMs, Integer totalMs, Integer completionMs, Integer sequence, Date date) {
        ChatMessage chatMessage = new ChatMessage();

        chatMessage.setChatId(chatHistoryId);
        chatMessage.setRole(role);
        chatMessage.setContent(content);
        chatMessage.setPromptTokens(promptTokens);
        chatMessage.setTotalTokens(totalTokens);
        chatMessage.setCompletionTokens(completionTokens);
        chatMessage.setPromptMs(promptMs);
        chatMessage.setTotalMs(totalMs);
        chatMessage.setCompletionMs(completionMs);
        chatMessage.setSequence(sequence);
        chatMessage.setCreateDate(date);
        chatMessage.setUpdateDate(date);

        chatMessageService.insert(chatMessage);
    }

    public String insertChatHistory(Long userId, String agentId, String deviceId, String faceId, Integer messageCount, Date date) {
        ChatHistory chatHistory = new ChatHistory();
        chatHistory.setUserId(userId);
        chatHistory.setAgentId(agentId);
        chatHistory.setDeviceId(deviceId);
        chatHistory.setFaceId(faceId);
        chatHistory.setMessageCount(messageCount);
        chatHistory.setCreateDate(date);
        chatHistory.setUpdateDate(date);

        chatHistoryService.insert(chatHistory);

        return chatHistory.getId();
    }

}